package com.wing.user.controller.admin;


import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wing.common.utils.JsonResult;
import com.wing.common.utils.LocalDateTimeUtils;
import com.wing.user.model.entity.ApplicationAuth;
import com.wing.user.model.entity.ApplicationMenu;
import com.wing.user.model.entity.User;
import com.wing.user.model.response.MenuVO;
import com.wing.user.service.ApplicationAuthService;
import com.wing.user.service.ApplicationMenuService;
import com.wing.user.service.MenuService;
import com.wing.user.service.UserService;
import com.wing.common.utils.RSAUtils;
import com.wing.web.annotation.AuthPass;
import com.wing.web.utils.JwtUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author
 */
@Api(value = "Admin-用户登录", tags = "用户登录")
@RestController
@RequestMapping("/user/admin/login")
@RequiredArgsConstructor
@Slf4j
public class LoginController {

    private final UserService userService;
    private final MenuService menuService;
    private final PasswordEncoder passwordEncoder;
    private final ApplicationAuthService applicationAuthService;
    private final ApplicationMenuService applicationMenuService;

    @AuthPass
    @ResponseBody
    @ApiOperation(value = "获取个人信息")
    @ApiImplicitParam(name = "access_token", value = "令牌", required = true, dataType = "String", paramType = "query")
    @GetMapping("/userInfo")
    public JsonResult userInfo() {
        User user = userService.getById(JwtUtils.getLoginUserId());
        user.setPassword("");
        return JsonResult.success(user);
    }

    @AuthPass
    @ResponseBody
    @ApiOperation(value = "获取个人信息")
    @ApiImplicitParam(name = "access_token", value = "令牌", required = true, dataType = "String", paramType = "query")
    @GetMapping("/getUserInfo")
    public JsonResult getUserInfo() {
        User user = userService.getByUserId(JwtUtils.getLoginUserId());

        String simplePwd=DigestUtil.md5Hex("123456");
        try{
            String pwd=RSAUtils.decryptByPrivateKey(RSAUtils.privateKey, user.getPasswordRsa());
            if (StringUtils.isBlank(user.getFaceData())&&(user.getIsUpdatePwd()!=null&&!user.getIsUpdatePwd())&&simplePwd.equalsIgnoreCase(pwd)){
                user.setIsUpdatePwd(false);
            }
        }catch (Exception e){
            log.error("decrypt fail",e);
        }
        user.setPassword("");
        user.setPasswordRsa("");
        return JsonResult.success(user);
    }

    @ApiOperation(value = "修改自己密码", notes = "修改自己密码")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "oldPassword", value = "原密码", required = true, dataType = "String", paramType = "form"),
            @ApiImplicitParam(name = "newPassword", value = "新密码", required = true, dataType = "String", paramType = "form")
    })
    @PutMapping("/password")
    public JsonResult updatePassword(String oldPassword, String newPassword) {
        User user = userService.getById(JwtUtils.getLoginUserId());
        if (!passwordEncoder.matches(oldPassword, user.getPassword())){
            return JsonResult.fail("原密码不正确");
        }
        user.setPassword(passwordEncoder.encode(newPassword));
        try{
            String passwordRsa = RSAUtils.encryptByPublicKey(RSAUtils.publicKey, newPassword);
            user.setPasswordRsa(passwordRsa);
        }catch (Exception e){
            log.error("encrypt fail",e);
        }
        if (userService.updateById(user)) {
            return JsonResult.success("修改成功");
        }
        return JsonResult.fail("修改失败");
    }

    @AuthPass
    @ResponseBody
    @ApiOperation(value = "获取所有菜单")
    @ApiImplicitParam(name = "access_token", value = "令牌", required = true, dataType = "String", paramType = "query")
    @GetMapping("/menu")
    public JsonResult userMenu() {
        try {
            List<MenuVO> menuVOList = new ArrayList<>();
            List<MenuVO> tempMenuVOList = menuService.listByUserId(JwtUtils.getLoginUserId());
            //判断 应用权限
            //如果配置了应用菜单，那需要判断此应用是否在使用时间范围内，时间已经过期就把菜单剔除
            //如果没有配置应用菜单，就把菜单当成基础功能，允许所有人使用
            List<ApplicationAuth> applicationAuthList = applicationAuthService.list();
            Map<Long, ApplicationMenu> tempMap = new HashMap<Long, ApplicationMenu>();
            for (ApplicationAuth applicationAuth : applicationAuthList) {
                //判断时间是否已经失效
                String authInfo = RSAUtils.decryptByPrivateKey(RSAUtils.privateKey, applicationAuth.getAuthInfo());
                JSONObject jsonObject = JSONObject.parseObject(authInfo);
                LocalDateTime startTime = LocalDateTimeUtils.convertStringToLDT(jsonObject.getString("startTime"), LocalDateTimeUtils.PATTERN);
                LocalDateTime endTime = LocalDateTimeUtils.convertStringToLDT(jsonObject.getString("endTime"), LocalDateTimeUtils.PATTERN);
                Integer status = jsonObject.getInteger("status");

                boolean isRange = LocalDateTimeUtils.judgeTimeRange(LocalDateTime.now(), startTime, endTime);
                if(!isRange || !"1".equals(status)){
                    //已过期,剔除应用菜单
                    QueryWrapper<ApplicationMenu> applicationMenuQueryWrapper = new QueryWrapper<ApplicationMenu>();
                    applicationMenuQueryWrapper.eq("app_id", applicationAuth.getAppId());
                    List<ApplicationMenu> applicationMenuList = applicationMenuService.list(applicationMenuQueryWrapper);
                    for(ApplicationMenu applicationMenu : applicationMenuList){
                        tempMap.put(applicationMenu.getMenuId(), applicationMenu);
                    }

                }
            }
            for(MenuVO menuVO : tempMenuVOList){
                if(tempMap.containsKey(menuVO.getId()) || menuVO.getName().equals("刀具柜权限") || menuVO.getName().equals("称重柜权限")){
                    continue;
                }
                menuVOList.add(menuVO);
            }
            return JsonResult.success(getMenuTree(menuVOList, -1L));
        }catch (Exception e){
            log.error("获取所有菜单异常:",e );
            return JsonResult.success("获取所有菜单异常:"+e.getMessage());
        }
    }

    /**
     * 递归转化树形菜单
     */
    private List<Map<String, Object>> getMenuTree(List<MenuVO> menus, Long parentId) {
        List<Map<String, Object>> list = new ArrayList<>();
        for (int i = 0; i < menus.size(); i++) {
            MenuVO temp = menus.get(i);
            if (parentId != null && temp.getParentId() != null && parentId.intValue() == temp.getParentId().intValue()) {
                Map<String, Object> map = new HashMap<>();
                map.put("name", temp.getName());
                map.put("icon", temp.getIcon());
                map.put("button", temp.getButton());
                map.put("url", StrUtil.isBlank(temp.getUrl()) ? "javascript:;" : temp.getUrl());
                List<Map<String, Object>> subMenus = getMenuTree(menus, menus.get(i).getId());
                map.put("subMenus", subMenus);

                //去除空菜单
                if(StringUtils.isBlank(temp.getUrl()) && subMenus.size() <= 0){
                    continue;
                }

                list.add(map);
            }
        }
        return list;
    }

    @PutMapping("/updatePassword")
    public JsonResult updatePasswordById(String oldPassword, String newPassword) {
        User user = userService.getById(JwtUtils.getLoginUserId());
        if (!passwordEncoder.matches(oldPassword, user.getPassword())){
            return JsonResult.fail("原密码不正确");
        }
        user.setPassword(passwordEncoder.encode(newPassword));
        try {
            // 加密
            String passwordRsa = RSAUtils.encryptByPublicKey(RSAUtils.publicKey, newPassword);
            user.setPasswordRsa(passwordRsa);
            user.setIsUpdatePwd(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (userService.updateById(user)) {
            return JsonResult.success("修改成功");
        }
        return JsonResult.fail("修改失败");
    }


}
